<template>
  <div id="map"></div>
  <div class="dialog" v-if="dialogData">
    <div class="close" @click="dialogData = null">关闭</div>
    <div style="margin-bottom: 10px">静态属性</div>
    <div v-for="(item, key) in dialogData.properties" :key="key">
      {{ key }}：{{ item }}
    </div>
    <div style="margin-top: 10px">计算属性</div>
    <div v-for="(list, key) in dialogData.results" :key="key">
      <div style="margin-top: 10px; color: red">{{ key }}</div>
      <div v-for="(item, index) in list" :key="index">
        {{ `${index}:00：${item}` }}
      </div>
    </div>
  </div>
  <!-- <textarea v-model="reportFile" class="textarea"></textarea> -->
</template>

<script setup>
import { Project, Workspace } from "epanet-js";
import { toGeoJson } from "./untils/EpanetToGeojson";
import geoJson from "./南沙模型-DN400.json";
import { readBinary } from "./untils/EpanetBinary";
import { default as proj4 } from "proj4";

import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import XYZ from "ol/source/XYZ";
import OSM from "ol/source/OSM";
import Feature from "ol/Feature";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Point from "ol/geom/Point";
import LineString from "ol/geom/LineString";
import { fromLonLat } from "ol/proj";
import { Circle, Fill, Stroke, Style, Icon } from "ol/style";

import pump_icon from "./images/pump.png";
import reservior_icon from "./images/reservior.png";
import tank_icon from "./images/tank.png";
import valve_icon from "./images/valve.png";

import { ref, onMounted } from "@vue/runtime-core";

let ws;
let model;
let fromProject;
let editData = ref({
  Junction: {},
  Reservior: {},
  Pipe: {},
  Valve: {},
  Pump: {},
  Tank: {},
});
const reportFile = ref("");
const dialogData = ref(null);

let map;
let mapData = {
  Junction: [],
  Reservior: [],
  Pipe: [],
  Valve: [],
  Pump: [],
  Tank: [],
};

function initModel(url) {
  return new Promise((resolve, reject) => {
    readTextFile(url)
      .then((text) => {
        fromProject = text;
        // Initialise a new Workspace and Project object
        ws = new Workspace();
        model = new Project(ws);
        // Write a copy of the inp file to the virtual workspace
        ws.writeFile("net1.inp", fromProject);
        // Runs toolkit methods: EN_open, EN_solveH & EN_close
        resolve();
      })
      .catch((error) => {
        console.error("Error reading file:", error);
        reject();
      });
  });
  // 异步读取文件
  async function readTextFile(path, encoding = "utf-8") {
    const file = new URL(path, import.meta.url);
    const response = await fetch(file);
    const text = await response.text();
    return text;
  }
}
function open() {
  model.open("net1.inp", "report.rpt", "out.bin");
}
function close() {
  model.close();
}
function run() {
  /*
  // 修改水泵开关
  const pumpIndex = model.getLinkIndex("SS05");
  // model.setLinkValue(linkIndex, 16, 0);
  const pumpValue = model.getLinkValue(linkIndex, 16);
  console.log("pumpValue:", pumpValue);
  */

  model.solveH();
  model.saveH();

  reportFile.value = ws.readFile("report.rpt");
  // const geoJson = toGeoJson(fromProject);
  console.log("geoJson:", geoJson);
  const resultView = ws.readFile("out.bin", "binary");
  const results = readBinary(resultView);
  console.log("results:", results);
  // 数据处理
  geoJson.links.features.forEach((link, index) => {
    mapData[link.properties.category].push({
      ...link,
      results: results.results.links[index],
    });
  });
  geoJson.nodes.features.forEach((node, index) => {
    if (editData.value.Junction[node.properties.id]) {
      let temp = editData.value.Junction[node.properties.id];
      node.properties[temp.type] = temp.value;
      if (temp.type == "pattern") node.properties.demand = 1;
    }
    mapData[node.properties.category].push({
      ...node,
      results: results.results.nodes[index],
    });
  });
  console.log("mapData:", mapData);
}
function getJunction(id, type) {
  const nodeIndex = model.getNodeIndex(id);
  const nodeValue = model.getNodeValue(nodeIndex, type);
  return nodeValue;
}
function setJunction(id, type, value) {
  const nodeIndex = model.getNodeIndex(id);
  if (type == 2) {
    // 修改节点24小时需水量
    model.addPattern(id); // 无需水量模式则需要新增
    const patternIndex = model.getPatternIndex(id); // 无需水量模式则需要新增
    model.setPattern(patternIndex, value);
    editData.value.Junction[id] = {
      type: "pattern",
      value: id,
    };
    model.setNodeValue(nodeIndex, 1, 1);
    model.setNodeValue(nodeIndex, type, patternIndex);
  } else {
    editData.value.Junction[id] = {
      type: "demand",
      value: value,
    };
    model.setNodeValue(nodeIndex, type, value);
  }
}
function getPipe(id, type) {
  // 修改管道开关
  const linkIndex = model.getLinkIndex(id);
  const linkValue = model.getLinkValue(linkIndex, type);
  return linkValue;
}
function setPipe(id, type, value) {
  const linkIndex = model.getLinkIndex(id);
  model.setLinkValue(linkIndex, type, value);
  editData.value.Pipe[id] = {
    type: "status",
    value: value,
  };
}
// 创建地图容器
function initMap() {
  map = new Map({
    target: "map",
    layers: [
      new TileLayer({
        source: new OSM(),
      }),
    ],
    // 南沙区中心点
    view: new View({
      center: fromLonLat([113.44, 22.73]),
      zoom: 10,
    }),
  });
}
// 绘制点要素
function addPoint(layerName) {
  const pointFeature = [];
  for (let i = 0; i <= mapData[layerName].length - 1; i++) {
    let feature = new Feature({
      geometry: new Point(
        fromLonLat(
          tranformCoordinate(mapData[layerName][i].geometry.coordinates)
        )
      ),
      name: layerName,
    });
    feature.setProperties({
      properties: mapData[layerName][i].properties,
      results: mapData[layerName][i].results,
    });
    pointFeature.push(feature);
  }

  // 创建矢量图层
  const vectorLayer = new VectorLayer({
    source: new VectorSource({
      features: pointFeature,
    }),
    style: new Style({
      image: new Circle({
        radius: 5,
        fill: new Fill({
          color: "rgba(0, 255, 0, 0.6)",
        }),
      }),
    }),
  });

  // 将矢量图层添加到地图上
  map.addLayer(vectorLayer);
}
// 绘制线要素
function addLine(layerName) {
  let color;
  switch (layerName) {
    case "Valve":
      color = "rgba(255, 0, 0, 0.6)";
      break;
    case "Pump":
      color = "rgba(255, 255, 0, 0.6)";
      break;
    default:
      color = "rgba(0, 0, 255, 0.6)";
      break;
  }
  const lineFeature = [];
  for (let i = 0; i <= mapData[layerName].length - 1; i++) {
    let res = [];
    mapData[layerName][i].geometry.coordinates.forEach((item) => {
      res.push(fromLonLat(tranformCoordinate(item)));
    });
    let feature = new Feature({
      geometry: new LineString(res),
      name: layerName,
    });
    feature.setProperties({
      properties: mapData[layerName][i].properties,
      results: mapData[layerName][i].results,
    });
    lineFeature.push(feature);
  }

  // 创建矢量图层
  const vectorLayer = new VectorLayer({
    source: new VectorSource({
      features: lineFeature,
    }),
    style: new Style({
      stroke: new Stroke({
        color: color,
        width: 10,
      }),
    }),
  });

  // 将矢量图层添加到地图上
  map.addLayer(vectorLayer);
}
// 绘制图标
function addIcon(layerName) {
  let icon_img;
  switch (layerName) {
    case "Valve":
      icon_img = valve_icon;
      break;
    case "Pump":
      icon_img = pump_icon;
      break;
    case "Tank":
      icon_img = tank_icon;
      break;
    case "Reservior":
      icon_img = reservior_icon;
      break;
  }
  const iconFeature = [];
  for (let i = 0; i <= mapData[layerName].length - 1; i++) {
    let point;
    if (["Valve", "Pump"].includes(layerName)) {
      point = [
        (mapData[layerName][i].geometry.coordinates[0][0] +
          mapData[layerName][i].geometry.coordinates[1][0]) /
          2,
        (mapData[layerName][i].geometry.coordinates[0][1] +
          mapData[layerName][i].geometry.coordinates[1][1]) /
          2,
      ];
    } else {
      point = mapData[layerName][i].geometry.coordinates;
    }
    let feature = new Feature({
      geometry: new Point(fromLonLat(tranformCoordinate(point))),
      name: layerName,
    });
    feature.setProperties({
      properties: mapData[layerName][i].properties,
      results: mapData[layerName][i].results,
    });
    iconFeature.push(feature);
  }

  // 创建矢量图层
  const vectorLayer = new VectorLayer({
    source: new VectorSource({
      features: iconFeature,
    }),
    style: new Style({
      image: new Icon({
        src: icon_img,
        scale: 0.5,
      }),
    }),
  });

  // 将矢量图层添加到地图上
  map.addLayer(vectorLayer);
}
function addHandler() {
  map.on("click", (ev) => {
    map.forEachFeatureAtPixel(ev.pixel, (feature) => {
      if (feature) {
        dialogData.value = feature.getProperties();
        console.log(dialogData.value);
      }
      return true; // 阻止事件穿透
    });
  });
}
// EPSG:2326坐标转WGS 84坐标
function tranformCoordinate(point) {
  // const fromProjection = `PROJCS["Hong Kong 1980 Grid System",GEOGCS["Hong Kong 1980",DATUM["Hong_Kong_1980",SPHEROID["International 1924",6378388,297],TOWGS84[-162.619,-276.959,-161.764,-0.067753,2.243648,1.158828,-1.094246]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4611"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",22.3121333333333],PARAMETER["central_meridian",114.178555555556],PARAMETER["scale_factor",1],PARAMETER["false_easting",836694.05],PARAMETER["false_northing",819069.8],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","2326"]]`;
  const fromProjection = `PROJCS["Beijing 1954 / 3-degree Gauss-Kruger CM 117E",GEOGCS["Beijing 1954",DATUM["Beijing_1954",SPHEROID["Krassowsky 1940",6378245,298.3],TOWGS84[31.4,-144.3,-74.8,0,0,0.814,-0.38]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4214"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",117],PARAMETER["scale_factor",1],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","2436"]]`;
  const toProjection = `GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]`;
  const newCoordinates = proj4(fromProjection, toProjection, point);
  return [newCoordinates[0] - 3, newCoordinates[1]]; // 返回数组格式
}

onMounted(async () => {
  await initModel("./南沙模型-DN400.inp");
  open();
  setJunction("72420", 1, 2);
  setJunction(
    "72420",
    2,
    [
      1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011,
      1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023,
      1024,
    ]
  );
  run();
  close();
  initMap();
  addHandler();
  addLine("Pipe");
  addLine("Valve");
  addLine("Pump");
  addPoint("Junction");
  addIcon("Reservior");
  addIcon("Tank");
  addIcon("Valve");
  addIcon("Pump");
});
</script>

<style scoped>
#map {
  width: 100vw;
  height: 100vh;
}
.textarea {
  position: fixed;
  top: 0;
  right: 0;
  width: 530px;
  height: 530px;
}
.dialog {
  position: fixed;
  top: 0;
  right: 0;
  width: 530px;
  height: 530px;
  overflow: auto;
  background: #fff;
  padding: 10px;
}
.close {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 20px;
  font-weight: bold;
  cursor: pointer;
}
</style>
